/*
 * This file is part of CompetitionGenerator.
 * CompetitionGenerator is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * CompetitionGenerator is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with CompetitionGenerator. If not, see <http://www.gnu.org/licenses/>.
 */
package competitiongenerator.entities;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Entity Competitor.
 * @author Ashitaka
 * @date 11-abr-2009
 */
public class CompetitorKarate {

    /**
     * Logger of the class Competitor.
     */
    private final static Logger logger = Logger.getLogger(CompetitorKarate.class.getName());
    /**
     * The identification number of the competitor.
     */
    private final UUID compID;
    /**
     * The name of the competitor.
     */
    private String compName;
    /**
     * The first surname of the competitor.
     */
    private String compFirstSurname;
    /**
     * The second surname of the competitor.
     */
    private String compSecondSurname;
    /**
     * The actual age of the competitor. Based on the birthday.
     */
    private int compAge;
    /**
     * The birthday of the competitor.
     */
    private Date compBirthday;
    /**
     * The federation number of the competitor.
     */
    private int compFederationNumber;
    /**
     * The country of the competitor.
     */
    private String compCountry;
    /**
     * The region of the competitor if the country is not enough.
     */
    private String compRegion;
    /**
     * The name of the competitor’s Sensei.
     */
    private ArrayList<String> compSensei;
    /**
     * The gym or the club where the competitor trains.
     */
    private ArrayList<String> compGym;
    /**
     * The weight of the competitor.
     */
    private double compWeight;
    /**
     * The range grades of the competitor.
     */
    private String compRange;

    /**
     * The possible range grades of the competitor.
     */
    public enum compRangeGrade {

        /**
         * White belt.
         */
        WHITE {

            /**
             * Override Method toString()
             */
            @Override
            public String toString() {
                return "White Belt";
            }
        },
        /**
         * Yellow belt.
         */
        YELLOW {

            /**
             * Override Method toString()
             */
            @Override
            public String toString() {
                return "Yellow Belt";
            }
        },
        /**
         * Orange belt.
         */
        ORANGE {

            /**
             * Override Method toString()
             */
            @Override
            public String toString() {
                return "Orange Belt";
            }
        },
        /**
         * Green belt.
         */
        GREEN {

            /**
             * Override Method toString()
             */
            @Override
            public String toString() {
                return "Green Belt";
            }
        },
        /**
         * Blue belt.
         */
        BLUE {

            /**
             * Override Method toString()
             */
            @Override
            public String toString() {
                return "Blue Belt";
            }
        },
        /**
         * Brown belt.
         */
        BROWN {

            /**
             * Override Method toString()
             */
            @Override
            public String toString() {
                return "White Belt";
            }
        },
        /**
         * Black belt.
         */
        BLACK {

            /**
             * Override Method toString()
             */
            @Override
            public String toString() {
                return "Black Belt";
            }
        },
        /**
         * Black belt 1st Dan.
         */
        BB1STDAN {

            /**
             * Override Method toString()
             */
            @Override
            public String toString() {
                return "Black Belt 1st Dan";
            }
        },
        /**
         * Black belt 2nd Dan.
         */
        BB2NDDAN {

            /**
             * Override Method toString()
             */
            @Override
            public String toString() {
                return "Black Belt 2nd Dan";
            }
        },
        /**
         * Black belt 3rd Dan.
         */
        BB3RDDAN {

            /**
             * Override Method toString()
             */
            @Override
            public String toString() {
                return "Black Belt 3rd Dan";
            }
        },
        /**
         * Black belt 4th Dan.
         */
        BB4THDAN {

            /**
             * Override Method toString()
             */
            @Override
            public String toString() {
                return "Black Belt 4th Dan";
            }
        },
        /**
         * Black belt 5th Dan.
         */
        BB5THDAN {

            /**
             * Override Method toString()
             */
            @Override
            public String toString() {
                return "Black Belt 5th Dan";
            }
        },
        /**
         * Black belt 6th Dan.
         */
        BB6THDAN {

            /**
             * Override Method toString()
             */
            @Override
            public String toString() {
                return "Black Belt 6th Dan";
            }
        },
        /**
         * Black belt 7th Dan.
         */
        BB7THDAN {

            /**
             * Override Method toString()
             */
            @Override
            public String toString() {
                return "Black Belt 7th Dan";
            }
        },
        /**
         * Black belt 8th Dan.
         */
        BB8THDAN {

            /**
             * Override Method toString()
             */
            @Override
            public String toString() {
                return "Black Belt 8th Dan";
            }
        },
        /**
         * Black belt 9th Dan.
         */
        BB9THDAN {

            /**
             * Override Method toString()
             */
            @Override
            public String toString() {
                return "Black Belt 9th Dan";
            }
        },
        /**
         * Black belt 10th Dan.
         */
        BB10THDAN {

            /**
             * Override Method toString()
             */
            @Override
            public String toString() {
                return "Black Belt 10th Dan";
            }
        }
    };

    /**
     * Basic constructor.
     * @param compName The name of the competitor.
     * @param comptFirstSurname The first surname of the competitor.
     * @param compRange The range of the competitor.
     */
    public CompetitorKarate(String compName, String comptFirstSurname, compRangeGrade compRange) {
        this.compID = UUID.randomUUID();
        setCompName(compName);
        setCompFirstSurname(comptFirstSurname);
        setCompRange(compRange);
        this.compAge = -1;
        this.compFederationNumber = -1;
        this.compWeight = -1.0;
        this.compBirthday = null;
        this.compCountry = null;
        this.compGym = new ArrayList<String>();
        this.compRegion = null;
        this.compSecondSurname = null;
        this.compSensei = new ArrayList<String>();
    }

    /**
     * Getter.
     * @return The compAge.
     */
    public int getCompAge() {
        return compAge;
    }

    /**
     * Setter. If the field compBirthday is already set, the age can not be
     * modified by calling this function, <b>setCompBirthday</b> function
     * must be called instead to refill this value.
     * @param compAge The age of the competitor.
     */
    public void setCompAge(int compAge) {
        if (getCompBirthday() == null) {
            this.compAge = compAge;
        } else {
            //TODO Warning pop-up here
            if (logger.isLoggable(Level.WARNING)) {
                logger.log(Level.WARNING, "Please, set a new birthday to modify the age.");
            }
        }
    }

    /**
     * Getter.
     * @return The compBirthday.
     */
    public Date getCompBirthday() {
        return compBirthday;
    }

    /**
     * Setter.
     * @param compBirthday The birthday of the competitor.
     */
    public void setCompBirthday(int year, int month, int day) {

        try {
            SimpleDateFormat dateFormatter = new SimpleDateFormat("dd/MM/yyyy");
            String bd = day + "/" + month + "/" + year;

            //TODO: Repaint here the obtained values (in the case that the date is wrong)
            //
            // REPAINT HERE
            //

            final Date birthday = dateFormatter.parse(bd);

            final long bdTime = birthday.getTime();
            Calendar calendar = Calendar.getInstance(Locale.getDefault());
            calendar.setTimeInMillis(Math.abs(bdTime - System.currentTimeMillis()));

            if (System.currentTimeMillis() - bdTime < 0) {
                if (logger.isLoggable(Level.WARNING)) {
                    logger.log(Level.WARNING, "Invalid date. Day not reached yet.");
                }
            } else {

                // Cleaning possible old birthday value
                this.compBirthday = null;

                // Setting the competitor age
                setCompAge(calendar.get(Calendar.YEAR) - 1970);

                // Setting the competitor birthday
                this.compBirthday = birthday;

                if (logger.isLoggable(Level.INFO)) {
                    StringBuffer sb = new StringBuffer();
                    sb.append("Date of input birthday: ");
                    sb.append(bd);
                    sb.append("\nA correct birthday value is: ");
                    sb.append(dateFormatter.format(birthday));
                    sb.append("\nNow printing the age: ");
                    sb.append(calendar.get(Calendar.YEAR) - 1970);
                    sb.append(" years; ");
                    sb.append(calendar.get(Calendar.MONTH));
                    sb.append(" months; ");
                    sb.append(calendar.get(Calendar.DAY_OF_MONTH));
                    sb.append(" days.");
                    sb.append("\nAGE:");
                    sb.append(this.getCompAge());
                    logger.log(Level.INFO, sb.toString());
                }
            }
        } catch (ParseException ex) {
            logger.log(Level.SEVERE, "Date Parse exception!.", ex);
        }
    }

    /**
     * Getter.
     * @return The compCountry.
     */
    public String getCompCountry() {
        return compCountry;
    }

    /**
     * Setter.
     * @param compCountry The country of the competitor.
     */
    public void setCompCountry(String compCountry) {
        this.compCountry = compCountry;
    }

    /**
     * Getter.
     * @return The compFederationNumber.
     */
    public int getCompFederationNumber() {
        return compFederationNumber;
    }

    /**
     * Setter.
     * @param compFederationNumber The competitor federation number.
     */
    public void setCompFederationNumber(int compFederationNumber) {
        this.compFederationNumber = compFederationNumber;
    }

    /**
     * Getter.
     * @return The compGym.
     */
    public ArrayList<String> getCompGym() {
        return compGym;
    }

    /**
     * Setter.
     * @param compGym  The gym/club where the competitor comes from.
     */
    public void setCompGym(String compGym) {
        this.compGym.add(compGym);
    }

    /**
     * Getter.
     * @return The compName.
     */
    public String getCompName() {
        return compName;
    }

    /**
     * Setter.
     * @param compName The name of the competitor.
     */
    public void setCompName(String compName) {
        this.compName = compName;
    }

    /**
     * Getter.
     * @return The compRange.
     */
    public String getCompRange() {
        return compRange;
    }

    /**
     * Setter.
     * @param compRange The range of the competitor.
     */
    public void setCompRange(compRangeGrade compRange) {
        this.compRange = compRange.toString();
    }

    /**
     * Getter.
     * @return The compRegion.
     */
    public String getCompRegion() {
        return compRegion;
    }

    /**
     * Setter.
     * @param compRegion The region of the competitor.
     */
    public void setCompRegion(String compRegion) {
        this.compRegion = compRegion;
    }

    /**
     * Getter.
     * @return The compSecondSurname.
     */
    public String getCompSecondSurname() {
        return compSecondSurname;
    }

    /**
     * Setter.
     * @param compSecondSurname The second surname of the competitor.
     */
    public void setCompSecondSurname(String compSecondSurname) {
        this.compSecondSurname = compSecondSurname;
    }

    /**
     * Getter.
     * @return The compSensei.
     */
    public ArrayList<String> getCompSensei() {
        return compSensei;
    }

    /**
     * Setter.
     * @param compSensei  The teacher of whom the competitor has received lessons.
     */
    public void setCompSensei(String compSensei) {
        this.compSensei.add(compSensei);
    }

    /**
     * Getter.
     * @return The compWeight.
     */
    public double getCompWeight() {
        return compWeight;
    }

    /**
     * Setter.
     * @param compWeight The weight of the competitor.
     */
    public void setCompWeight(double compWeight) {
        this.compWeight = compWeight;
    }

    /**
     * Getter.
     * @return The comptFirstSurname.
     */
    public String getCompFirstSurname() {
        return compFirstSurname;
    }

    /**
     * Setter.
     * @param comptFirstSurname The first surname of the competitor.
     */
    public void setCompFirstSurname(String comptFirstSurname) {
        this.compFirstSurname = comptFirstSurname;
    }

    /**
     * Getter.
     * @return The competitor unique ID.
     */
    public UUID getCompID() {
        return compID;
    }

    /**
     * Auxiliar function that returns the competitor range grade from a given
     * pre-defined string.
     * <p><b>CODES:</b></p>
     * <p>white = WHITE</p>
     * <p>yellow = YELLOW</p>
     * <p>orange = ORANGE</p>
     * <p>green = GREEN</p>
     * <p>blue = BLUE</p>
     * <p>brown = BROWN</p>
     * <p>black = BLACK</p>
     * <p>black1 = BB1STDAN</p>
     * <p>black2 = BB2NDDAN</p>
     * <p>black3 = BB3RDDAN</p>
     * <p>black4 = BB4THDAN</p>
     * <p>black5 = BB5THDAN</p>
     * <p>black6 = BB6THDAN</p>
     * <p>black7 = BB7THDAN</p>
     * <p>black8 = BB8THDAN</p>
     * <p>black9 = BB9THDAN</p>
     * <p>black10 = BB10THDAN</p>
     * @param range The range it is desired to code.
     * @return The compRangeGrade correspondant to the range grade, or WHITE
     * by default if no grade matches with the range.
     */
    public static compRangeGrade getCompRangeGrade(String range) {
        compRangeGrade crg = null;
        if (range.equalsIgnoreCase("white")) {
            crg = crg.WHITE;
        } else if (range.equalsIgnoreCase("yellow")) {
            crg = crg.YELLOW;
        } else if (range.equalsIgnoreCase("orange")) {
            crg = crg.ORANGE;
        } else if (range.equalsIgnoreCase("green")) {
            crg = crg.GREEN;
        } else if (range.equalsIgnoreCase("blue")) {
            crg = crg.BLUE;
        } else if (range.equalsIgnoreCase("brown")) {
            crg = crg.BROWN;
        } else if (range.equalsIgnoreCase("black")) {
            crg = crg.BLACK;
        } else if (range.equalsIgnoreCase("black1")) {
            crg = crg.BB1STDAN;
        } else if (range.equalsIgnoreCase("black2")) {
            crg = crg.BB2NDDAN;
        } else if (range.equalsIgnoreCase("black3")) {
            crg = crg.BB3RDDAN;
        } else if (range.equalsIgnoreCase("black4")) {
            crg = crg.BB4THDAN;
        } else if (range.equalsIgnoreCase("black5")) {
            crg = crg.BB5THDAN;
        } else if (range.equalsIgnoreCase("black6")) {
            crg = crg.BB6THDAN;
        } else if (range.equalsIgnoreCase("black7")) {
            crg = crg.BB7THDAN;
        } else if (range.equalsIgnoreCase("black8")) {
            crg = crg.BB8THDAN;
        } else if (range.equalsIgnoreCase("black9")) {
            crg = crg.BB9THDAN;
        } else if (range.equalsIgnoreCase("black10")) {
            crg = crg.BB10THDAN;
        } else {
            if (logger.isLoggable(Level.WARNING)) {
                logger.log(Level.WARNING,
                        "No range matches with your request, " +
                        "so White Belt has been set.");
            }
            crg = crg.WHITE;
        }
        return crg;
    }

    /**
     * The competitor content.
     * @return The competitor fields as String.
     */
    @Override
    public String toString() {

        StringBuffer bs = new StringBuffer();
        bs.append("<-- Competitor -->");
        bs.append("\nID:");
        bs.append(getCompID());
        bs.append("\nName: ");
        bs.append(getCompName());
        bs.append("\nFirst Surname: ");
        bs.append(getCompFirstSurname());

        if (getCompSecondSurname() != null) {
            bs.append("\nSecond Surname: ");
            bs.append(getCompSecondSurname());
        }
        if (getCompAge() >= 0) {
            bs.append("\nAge: ");
            bs.append(this.getCompAge());
        }
        if (getCompBirthday() != null) {
            bs.append("\nBirthday: ");
            bs.append(getCompBirthday());
        }
        if (getCompCountry() != null) {
            bs.append("\nCountry: ");
            bs.append(getCompCountry());
        }
        if (getCompRegion() != null) {
            bs.append("\nRegion: ");
            bs.append(getCompRegion());
        }
        if (getCompFederationNumber() >= 0) {
            bs.append("\nFederation Number: ");
            bs.append(getCompFederationNumber());
        }
        if (!getCompSensei().isEmpty()) {
            for (String sensei : getCompSensei()) {
                bs.append("\nSensei: ");
                bs.append(sensei);
            }
        }
        if (!getCompGym().isEmpty()) {
            for (String gym : getCompGym()) {
                bs.append("\nGym: ");
                bs.append(gym);
            }
        }
        if (getCompRange() != null) {
            bs.append("\nRange: ");
            bs.append(getCompRange());
        }
        if (getCompWeight() >= 0) {
            bs.append("\nWeight: ");
            bs.append(getCompWeight());
        }
        return bs.toString();
    }
}
